﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Linq;
using Microsoft.Xna.Framework.Input;

namespace Pavilion.GameTools
{
    public class CharacterInputTool : GameToolBase
    {
        public event Action<IEnumerable<CharacterInput>> PressedInputChanged, ReleasedInputChanged;

        public IEnumerable<CharacterInput> PressedInput { get { return pressedInput; } }
        public IEnumerable<CharacterInput> ReleasedInput { get { return releasedInput; } }

        private List<CharacterInput> pressedInput, releasedInput;
        private KeyboardTool keyboardTool;
        private XElement xmlPropertiesHolder;

        public CharacterInputTool()
        {
            pressedInput = new List<CharacterInput>();
            releasedInput = new List<CharacterInput>();
        }

        public override void Initialize(GameItem gameItem)
        {
            gameItem.Loaded += (GameItem item) =>
            {
                keyboardTool = item.ObtainTool<KeyboardTool>();

                DeserializeAndRegisterInput(xmlPropertiesHolder, CharacterInput.Grab);
                DeserializeAndRegisterInput(xmlPropertiesHolder, CharacterInput.Jump);
                DeserializeAndRegisterInput(xmlPropertiesHolder, CharacterInput.Left);
                DeserializeAndRegisterInput(xmlPropertiesHolder, CharacterInput.Right);
                DeserializeAndRegisterInput(xmlPropertiesHolder, CharacterInput.Up);
                DeserializeAndRegisterInput(xmlPropertiesHolder, CharacterInput.Down);
            };
        }

        public override void Deserialize(XElement xmlProperties)
        {
            this.xmlPropertiesHolder = xmlProperties;
        }

        public override void Serialize() { }

        private void DeserializeAndRegisterInput(XElement xmlProperties, CharacterInput characterInput)
        {
            XAttribute keyAttribute = xmlProperties.Attribute(characterInput.ToString());

            if (keyAttribute == null)
                return;

            Keys key = (Keys)Enum.Parse(typeof(Keys), keyAttribute.Value);
            RegisterCharacterInput(key, characterInput);
        }

        private void RegisterCharacterInput(Keys key, CharacterInput characterInput)
        {
            releasedInput.Add(characterInput);

            keyboardTool.RegisterKeyPressed(() => { pressedInput.Add(characterInput); releasedInput.Remove(characterInput); OnPressedInputChanged(); }, key);
            keyboardTool.RegisterKeyReleased(() => { releasedInput.Add(characterInput); 
                pressedInput.Remove(characterInput); 
                OnReleaseInputChanged(); }, key);
        }

        private void OnReleaseInputChanged()
        {
            if (ReleasedInputChanged != null)
                ReleasedInputChanged(ReleasedInput);
        }

        private void OnPressedInputChanged()
        {
            if (PressedInputChanged != null)
                PressedInputChanged(PressedInput);
        }
    }

    public enum CharacterInput
    {
        Jump,
        Grab,
        Left,
        Right,
        Up,
        Down
    }
}
